﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace QLFUI
{
    /// <summary>
    /// 所有QLF控件的基类
    /// 提供一些通用的方法和属性
    /// </summary>
    [ToolboxItem(false)] /*不在工具箱中显示*/
    public class QLFControlBase : UserControl
    {
        #region - 变量 -

        /// <summary>
        /// 当前边框使用的颜色
        /// </summary>
        protected Color currentBorderColor = Color.FromArgb(186, 197, 207);
        /// <summary>
        /// 当前内边框使用的颜色
        /// </summary>
        protected Color currentInnerBorderColor = Color.Transparent;
        /// <summary>
        /// 当前背景使用的颜色起始色
        /// </summary>
        protected Color currentBackColorStart = Color.FromArgb(238, 241, 243);
        /// <summary>
        /// 当前背景使用的颜色结束色
        /// </summary>
        protected Color currentBackColorEnd = Color.FromArgb(225, 230, 235);

        private BorderRadiu currentBorderRadiu = new BorderRadiu();

        protected Matrix currentMatrix = new Matrix();


        //normal
        private Color borderColor = Color.FromArgb(186, 197, 207);
        private Color innerBorderColor = Color.Transparent;
        private Color backColorStart = Color.FromArgb(238, 241, 243);
        private Color backColorEnd = Color.FromArgb(225, 230, 235);
        //hover
        private Color borderColorHover = Color.FromArgb(146, 159, 173);
        private Color innerBorderColorHover = Color.Transparent;
        private Color backColorStartHover = Color.FromArgb(216, 222, 227);
        private Color backColorEndHover = Color.FromArgb(205, 212, 217);
        //press
        private Color borderColorPress = Color.FromArgb(147, 159, 143);
        private Color innerBorderColorPress = Color.Transparent;
        private Color backColorStartPress = Color.FromArgb(199, 205, 211);
        private Color backColorEndPress = Color.FromArgb(187, 195, 200);
        //unenabled
        private Color borderColorUnEnable = Color.FromArgb(205, 214, 221);
        private Color innerBorderColorUnEnable = Color.FromArgb(240, 248, 250);
        private Color backColorStartUnEnable = Color.FromArgb(247, 252, 254);
        private Color backColorEndUnEnable = Color.FromArgb(230, 240, 243);
        private Color foreColorUnEnable = Color.Gray;

        #endregion

        #region - 属性 -

        #region normal


        [Category("1_QLFUI"), Description("边框颜色")]
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                borderColor = value;

                if (DesignMode)
                {
                    currentBorderColor = value;
                    Invalidate();
                }
            }
        }

        [Category("1_QLFUI"), Description("内边框颜色，紧贴着边框内部")]
        public Color InnerBorderColor
        {
            get { return innerBorderColor; }
            set
            {
                innerBorderColor = value;

                if (DesignMode)
                {
                    currentInnerBorderColor = value;
                    Invalidate();
                }
            }
        }

        [Category("1_QLFUI"), Description("背景起始色")]
        public Color BackColorStart
        {
            get { return backColorStart; }
            set
            {
                backColorStart = value;

                if (DesignMode)
                {
                    currentBackColorStart = value;
                    Invalidate();
                }
            }
        }

        [Category("1_QLFUI"), Description("背景结束色")]
        public Color BackColorEnd
        {
            get { return backColorEnd; }
            set
            {
                backColorEnd = value;
                if (DesignMode)
                {
                    currentBackColorEnd = value;
                    Invalidate();
                }
            }
        }

        #endregion

        #region Hover

        [Category("1_QLFUI_Hover"), Description("鼠标移动到控件上的边框颜色")]
        public Color BorderColorHover
        {
            get { return borderColorHover; }
            set { borderColorHover = value; }
        }

        [Category("1_QLFUI_Hover"), Description("鼠标移动到控件上的内边框颜色")]
        public Color InnerBorderColorHover
        {
            get { return innerBorderColorHover; }
            set { innerBorderColorHover = value; }
        }

        [Category("1_QLFUI_Hover"), Description("鼠标移动到控件上的背景颜色起始色")]
        public Color BackColorStartHover
        {
            get { return backColorStartHover; }
            set { backColorStartHover = value; }
        }

        [Category("1_QLFUI_Hover"), Description("鼠标移动到控件上的背景颜色结束色")]
        public Color BackColorEndHover
        {
            get { return backColorEndHover; }
            set { backColorEndHover = value; }
        }

        #endregion

        #region Press

        [Category("1_QLFUI_Press"), Description("鼠标按下时的边框颜色")]
        public Color BorderColorPress
        {
            get { return borderColorPress; }
            set { borderColorPress = value; }
        }

        [Category("1_QLFUI_Press"), Description("鼠标按下时的内边框颜色")]
        public Color InnerBorderColorPress
        {
            get { return innerBorderColorPress; }
            set { innerBorderColorPress = value; }
        }

        [Category("1_QLFUI_Press"), Description("鼠标按下时的背景颜色起始色")]
        public Color BackColorStartPress
        {
            get { return backColorStartPress; }
            set { backColorStartPress = value; }
        }

        [Category("1_QLFUI_Press"), Description("鼠标按下时的背景颜色结束色")]
        public Color BackColorEndPress
        {
            get { return backColorEndPress; }
            set { backColorEndPress = value; }
        }

        #endregion

        #region UnEnable

        [Category("1_QLFUI_UnEnable"), Description("Enable = false 时的边框颜色")]
        public Color BorderColorUnEnable
        {
            get { return borderColorUnEnable; }
            set { borderColorUnEnable = value; }
        }

        [Category("1_QLFUI_UnEnable"), Description("Enable = false 时的内边框颜色")]
        public Color InnerBorderColorUnEnable
        {
            get { return innerBorderColorUnEnable; }
            set { innerBorderColorUnEnable = value; }
        }

        [Category("1_QLFUI_UnEnable"), Description("Enable = false 时的起始颜色")]
        public Color BackColorStartUnEnable
        {
            get { return backColorStartUnEnable; }
            set { backColorStartUnEnable = value; }
        }

        [Category("1_QLFUI_UnEnable"), Description("Enable = false 时的结束颜色")]
        public Color BackColorEndUnEnable
        {
            get { return backColorEndUnEnable; }
            set { backColorEndUnEnable = value; }
        }

        [Category("1_QLFUI_UnEnable"), Description("Enable = false 时的字体颜色")]
        public Color ForeColorUnEnable
        {
            get { return foreColorUnEnable; }
            set { foreColorUnEnable = value; }
        }

        #endregion

        //隐藏基类的BackColor，保持基类的BackColor永远为透明色（构造函数中设置）
        [Browsable(false)]
        public new Color BackColor { get; set; }

        [Category("2_QLFUI_Other"), Description("边框弯曲程度，值越大越弯曲，0为不弯曲")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BorderRadiu BorderRadius
        {
            get { return currentBorderRadiu; }
        }

        [Category("2_QLFUI_Other"), Description("画背景时的方向")]
        public LinearGradientMode BackColorMode { get; set; }

        #endregion

        #region - 构造函数 -

        protected QLFControlBase()
        {
            currentBorderColor = BorderColor;
            currentInnerBorderColor = InnerBorderColor;
            //真正的背景色永远是透明色，这样在处理圆角背景的时候就比较好弄了
            base.BackColor = Color.Transparent;
            BackColor = Color.FromArgb(232, 236, 239);

        }

        #endregion

        #region - 事件 -

        protected override void OnLoad(EventArgs e)
        {
            //设置双缓冲
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);

            base.OnLoad(e);
        }

        #endregion

        #region - 动画 -

        private float test = 1.0f;
        protected void fz()
        {

        }

        #endregion

        #region - 辅助方法 -

        #region 绘画

        /// <summary>
        /// 画背景，使用currentBackColor颜色
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rectangle"></param>
        protected virtual void DrawBackColor(Graphics g, Rectangle rectangle)
        {

            using (LinearGradientBrush backgroundBrush = new LinearGradientBrush(rectangle,
                    currentBackColorStart, currentBackColorEnd, BackColorMode))
            {
                //if (BorderRadius.LeftTop == 0)
                //{
                //    //这里完全覆盖没有事情，因为下面的边框会将其覆盖
                //    g.FillRectangle(backgroundBrush, rectangle);
                //}
                //else
                //{
                g.FillPath(backgroundBrush, DrawRoundRect(rectangle.X,
                                                          rectangle.Y,
                                                          rectangle.Width - 1,
                                                          rectangle.Height - 1, BorderRadius.LeftTop, BorderRadius.RightTop, BorderRadius.RightBottom, BorderRadius.LeftBottom));
                // }
            }
        }

        /// <summary>
        /// 画边框，使用currentBorderColor颜色
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rectangle"></param>
        protected virtual void DrawBorder(Graphics g, Rectangle rectangle)
        {

            using (Pen pen = new Pen(currentBorderColor))
            {
                //if (BorderRadiusStruct == 0)
                //{
                //    g.DrawRectangle(pen, new Rectangle(rectangle.X,
                //                                       rectangle.Y,
                //                                       rectangle.Width - 1,
                //                                       rectangle.Height - 1));
                //}
                //else
                //{
                g.DrawPath(pen, DrawRoundRect(rectangle.X,
                                              rectangle.Y,
                                              rectangle.Width - 1,
                                              rectangle.Height - 1, BorderRadius.LeftTop, BorderRadius.RightTop, BorderRadius.RightBottom, BorderRadius.LeftBottom));
                //}
            }

        }

        /// <summary>
        /// 画内边框，使用currentInnerBackColor颜色
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rectangle"></param>
        protected virtual void DrawInnerBorder(Graphics g, Rectangle rectangle)
        {

            using (Pen pen = new Pen(currentInnerBorderColor))
            {
                //if (BorderRadiusStruct == 0)
                //{
                //    g.DrawRectangle(pen, new Rectangle(rectangle.X + 1,
                //                                       rectangle.Y + 1,
                //                                       rectangle.Width - 3,
                //                                       rectangle.Height - 3));
                //}
                //else
                //{
                g.DrawPath(pen, DrawRoundRect(rectangle.X + 1,
                                              rectangle.Y + 1,
                                              rectangle.Width - 3,
                                              rectangle.Height - 3, BorderRadius.LeftTop, BorderRadius.RightTop, BorderRadius.RightBottom, BorderRadius.LeftBottom));
                //}
            }

        }

        #endregion

        /// <summary>
        /// 该控件所在的窗体是否开启了透明效果，如果窗体开启透明
        /// 则其下所有控件都开启此透明效果
        /// </summary>
        protected bool IsEnableTransparent()
        {
            //在design模式下，这里会是vs崩溃
            if (!DesignMode)
            {
                return IsEnableTransparent(this);
            }
            return false;
        }

        private bool IsEnableTransparent(Control control)
        {
            if (control.Parent != null && control.Parent is FormBase)
            {
                FormBase formBase = control.Parent as FormBase;
                return formBase.EnableTransparent;
            }
            if(control.Parent ==null)
            {
                return false;
            }
            return IsEnableTransparent(control.Parent);
        }

        protected virtual void SetNormalState()
        {
            currentBorderColor = BorderColor;
            currentBackColorStart = BackColorStart;
            currentBackColorEnd = BackColorEnd;
            currentInnerBorderColor = InnerBorderColor;
        }

        protected virtual void SetHoverState()
        {
            currentBorderColor = BorderColorHover;
            currentBackColorStart = BackColorStartHover;
            currentBackColorEnd = BackColorEndHover;
            currentInnerBorderColor = InnerBorderColorHover;
        }

        protected virtual void SetPressState()
        {
            currentBorderColor = BorderColorPress;
            currentBackColorStart = BackColorStartPress;
            currentBackColorEnd = BackColorEndPress;
            currentInnerBorderColor = InnerBorderColorPress;
        }

        /// <summary>
        /// 绘制圆角矩形
        /// </summary>
        protected GraphicsPath DrawRoundRect(int x, int y, int width, int height, int radius)
        {
            return DrawRoundRect(x, y, width, height, radius, radius, radius, radius);
        }

        /// <summary>
        /// 绘制圆角矩形
        /// </summary>
        protected GraphicsPath DrawRoundRect(Rectangle rect, int radius)
        {
            return DrawRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius);
        }

        /// <summary>
        /// 绘制圆角矩形（提供四个角自定义角度）
        /// </summary>
        /// <param name="r"></param>
        /// <param name="r1">左上角角度</param>
        /// <param name="r2">右上角角度</param>
        /// <param name="r3">右下角角度</param>
        /// <param name="r4">左下角角度</param>
        /// <returns></returns>
        protected GraphicsPath DrawRoundRect(Rectangle r, int r1, int r2, int r3, int r4)
        {
            float x = r.X, y = r.Y, w = r.Width, h = r.Height;
            GraphicsPath rr = new GraphicsPath();
            rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
            rr.AddLine(x + r1, y, x + w - r2, y);
            rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
            rr.AddLine(x + w, y + r2, x + w, y + h - r3);
            rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
            rr.AddLine(x + w - r3, y + h, x + r4, y + h);
            rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
            rr.AddLine(x, y + h - r4, x, y + r1);
            return rr;
        }

        /// <summary>
        /// 绘制圆角矩形（提供四个角自定义角度）
        /// </summary>
        protected GraphicsPath DrawRoundRect(float x, float y, float w, float h, int r1, int r2, int r3, int r4)
        {
            GraphicsPath rr = new GraphicsPath();
            rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
            rr.AddLine(x + r1, y, x + w - r2, y);
            rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
            rr.AddLine(x + w, y + r2, x + w, y + h - r3);
            rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
            rr.AddLine(x + w - r3, y + h, x + r4, y + h);
            rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
            rr.AddLine(x, y + h - r4, x, y + r1);
            return rr;
        }

        /// <summary>
        /// 得到两种颜色的过渡色（1代表开始色，100表示结束色）
        /// </summary>
        /// <param name="c">开始色</param>
        /// <param name="c2">结束色</param>
        /// <param name="value">需要获得的度</param>
        /// <returns></returns>
        protected Color GetIntermediateColor(Color c, Color c2, int value)
        {
            float pc = value * 1.0F / 100;

            int ca = c.A, cr = c.R, cg = c.G, cb = c.B;
            int c2a = c2.A, c2r = c2.R, c2g = c2.G, c2b = c2.B;

            int a = (int)Math.Abs(ca + (ca - c2a) * pc);
            int r = (int)Math.Abs(cr - ((cr - c2r) * pc));
            int g = (int)Math.Abs(cg - ((cg - c2g) * pc));
            int b = (int)Math.Abs(cb - ((cb - c2b) * pc));

            if (a > 255) { a = 255; }
            if (r > 255) { r = 255; }
            if (g > 255) { g = 255; }
            if (b > 255) { b = 255; }

            return (Color.FromArgb(a, r, g, b));
        }

        /// <summary>
        /// 通知控件所在的TFormEx更新该控件状态
        /// </summary>
        /// <remarks>
        /// 此方法所处的级别与Invalidate类此，所以在调用Invalidate地方应该调用此方法
        /// </remarks>
        protected void NotifyUpdate()
        {
            //控件开启了透明情况下采取通知绘画更新
            if (IsEnableTransparent())
            {
                if (Parent is FormEx)
                {
                    ((FormEx)Parent).UpdateControl(this);
                }
            }

        }

        #endregion

    }
}